/*
文件操作
操作文件的三大类
  ofstream： 写操作
  ifstream: 读操作
  fstream: 读写操作

文本文件，文件以文本的ASCII码形式存储在计算机中
写文件的步骤
  1.包含头文件 #include <fstream>
  2.创建流对象 ofstream ofs;  // 或者 fstream
  3.打开文件 ofs.open(文件路径， 打开方式);
  4.写数据 ofs << "写入的数据";
  5.关闭文件 ofs.close();

文件打开方式
  打开方式	解释
  ios::in	    为读文件而打开文件
  ios::out	为写文件而打开文件
  ios::ate	初始位置：文件尾
  ios::app	追加方式写文件
  ios::trunc	如果文件存在先删除，再创建
  ios::binary	二进制方式
文件打开方式可以配合使用，利用|操作符， 例如 用二进制方式写文件 ios::binary | ios::out

文件流指针位置
  函数：seekg() 用于输入文件流，seekp()用于输出文件流。两个函数用法一致
  它支持三种定位模式：ios::beg（文件开头）、ios::cur（当前位置）和 ios::end（文件末尾）。
  ifs.seekg(5, ios::beg);  // 将指针移动到文件开头后第 5 个字节
  与 tellg 配合：可以使用 tellg 获取当前指针位置， 输出文件用tellp()
  streampos pos = ifs.tellg();
  cout << "当前指针位置: " << pos << endl;

读文件与写文件步骤相似，但是读取方式相对于比较多
读文件的步骤
  1.包含头文件 #include <fstream>
  2.创建流对象 ifstream ifs; // 或者 fstream
  3.打开文件并判断文件是否打开成功 ifs.open(文件路径， 打开方式);
  4.读数据，有四种方式读取
  5.关闭文件 ifs.close();

二进制文件，存储的是二进制，打开方式要指定为 ios::binary
写文件，主要利用流对象调用成员函数write，
函数原型：ostream& write(const char * buffer,int len);
参数解释：字符指针buffer指向内存中一段存储空间。len是读写的字节数

读文件，主要利用流对象成员函数read,
函数原型：istream& read(char *buffer,int len);
参数解释：字符指针buffer指向内存中一段存储空间。len是读写的字节数

*/
#include <iostream>
#include <fstream>
#include <string>
using namespace std;

void write_text_to_file()
{
  // 创建对象流
  ofstream ofs;

  // 打开文件
  ofs.open("../static/test.text", ios::out);

  // 写数据
  ofs << "你好 c plus plus" << endl;
  ofs << "你好 c++" << endl;
  ofs << "你好 世界" << endl;

  // 关闭文件
  ofs.close();
}

void read_text_from_file()
{
  // 创建流对象
  ifstream ifs;

  // 打开文件
  ifs.open("../static/test.text", ios::in);
  // 判断文件是否打开成功
  if (!ifs.is_open())
  {
    cout << "File open fail..." << endl;
    return;
  }

  // // 第一钟方式读文件
  // char buf[1024] = {0};
  // while (ifs >> buf)
  // {
  //   cout << "Reading data is: " << buf << endl;
  //   // Reading data is: 你好
  //   // Reading data is: c
  //   // Reading data is: plus
  //   // Reading data is: plus
  //   // Reading data is: 你好
  //   // Reading data is: c++
  //   // Reading data is: 你好
  //   // Reading data is: 世界
  // }

  // // 第二钟读方式
  // char buf[1024] = {0};
  // while (ifs.getline(buf, sizeof(buf)))
  // {
  //   cout << "Reading data is: " << buf << endl;
  //   // Reading data is: 你好 c plus plus
  //   // Reading data is: 你好 c++
  //   // Reading data is: 你好 世界
  // }

  // // 第三种读方式
  // string buf;
  // while (getline(ifs, buf))
  // {
  //   cout << "Reading data is: " << buf << endl;
  //   // Reading data is: 你好 c plus plus
  //   // Reading data is: 你好 c++
  //   // Reading data is: 你好 世界
  // }

  // 第四种读方式
  char c;
  while ((c = ifs.get()) != EOF)
  {
    cout << c;
    // 你好 c plus plus
    // 你好 c++
    // 你好 世界
  }

  // 关闭文件
  ifs.close();
}

class Persion
{
public:
  char m_name[64];
  int m_age;
};

void write_binary_to_file()
{
  Persion persion = {"alias", 18};
  cout << "persion.m_name = " << persion.m_name << " persion.m_age = " << persion.m_age << endl;
  // ofstream ofs;
  // ofs.open("../static/test.binary", ios::out|ios::binary);
  ofstream ofs("../static/test.binary", ios::out | ios::binary);
  ofs.write((const char *)&persion, sizeof(persion));
  ofs.close();
}

void read_binary_from_file()
{
  ifstream ifs("../static/test.binary", ios::in | ios::binary);
  Persion persion;
  ifs.read((char *)&persion, sizeof(persion));
  cout << "persion.m_name = " << persion.m_name << " persion.m_age = " << persion.m_age << endl;
  ifs.close();
}

int main()
{
  write_text_to_file();
  read_text_from_file();
  write_binary_to_file();
  read_binary_from_file();

  return 0;
}